﻿// ## 2023/10/30 # 铃 # 重构部分逻辑,. ##
// ## 2022/11/08 # 铃 # 火烧对新的城防系统也有伤害. ##
// ## 2022/11/08 # 铃 # 对新城防系统使用新的对数函数作为伤害算法,使其更加平滑. ##
// ## 2022/08/01 # 铃 # 为新城防系统重写了伤害算法，加入被包围时减士气的设定，取消了被包围时减兵力的设定。 ##
// ## 2022/02/14 # 江东新风 # 部分常量中文化 ##
// ## 2021/10/24 # 江东新风 # 将pk::add_troops换成ch::add_troops以修正显示错误 ##
// ## 2020/10/30 # 江东新风 # 同步马术书大神的更新 ##

namespace 据点战斗效果
{
    class Main
    {
        Main()
        {
            pk::bind(107, pk::trigger107_t(onNewDay));
        }

        void onNewDay()
        {
            if (pk::is_campaign())
                return;

            if (pk::get_elapsed_months() <= 1)
                return;

            for (int i = 0; i < 据点_末; i++)
            {
                pk::building @building = pk::get_building(i);
                if (pk::is_valid_person_id(pk::get_taishu_id(building)))
                {
                    // 这几个功能有太守方可实现
                    据点_筑城效果(building);
                    据点_火计反击(building);
                    据点_奏乐效果(building);
                    据点_名声效果(building);
                }
                据点_包围效果(building);
                据点_燃烧效果(building);

            }
        }

        //-------------------------------------------------------------------------------------------------
        void 据点_火计反击(pk::building @building)
        {

            int msg_count = 0;
            int dst_range = (building.get_id() < 城市_末) ? 2 : 1;

            array<pk::point> arr = pk::range(building.pos, dst_range, dst_range);
            for (int j = 0; j < int(arr.length); j++)
            {
                pk::unit @unit = pk::get_unit(arr[j]);
                if (unit !is null and pk::is_enemy(unit, building))
                {
                    int fire_chance = 0;
                    int fire_timer = 0;
                    int fire_person_id = 0;

                    pk::person @taishu = pk::get_person(pk::get_taishu_id(building));

                    int stat_delta = 100;
                    if (taishu is null)
                        stat_delta = 0;
                    else if (unit.leader < 武将_灵帝 or unit.leader > 武将_学者)
                        stat_delta = pk::max(0, taishu.stat[武将能力_智力] - unit.attr.stat[部队能力_智力]);

                    // 발동 확률 및 타이머 설정
                    if (taishu is null)
                        fire_chance = 0;
                    else if (pk::is_valid_person_id(building.who_has_skill(特技_火神)))
                    {
                        fire_chance = 100;
                        fire_timer = 1;
                        fire_person_id = building.who_has_skill(特技_火神);
                    }
                    else if (pk::is_valid_person_id(building.who_has_skill(特技_火攻)))
                    {
                        fire_chance = pk::min(100, stat_delta + 50);
                        fire_timer = 1;
                        fire_person_id = building.who_has_skill(特技_火攻);
                    }
                    else
                    {
                        fire_chance = pk::min(100, stat_delta);
                        fire_person_id = pk::get_taishu_id(building);
                    }

                    if (pk::rand_bool(fire_chance) and !pk::is_on_fire(unit.pos))
                    {
                        if (pk::is_in_screen(building.pos) and msg_count == 0)
                        {
                            msg_count = 1;
                            pk::say(pk::encode("把火燃起来"), pk::get_person(fire_person_id));
                            pk::play_se(0x39, building.pos);
                            switch (pk::rand(3))
                            {
                                case 0:
                                    pk::play_voice(0x33, pk::get_person(fire_person_id));
                                    break;
                                case 1:
                                    pk::play_voice(0x34, pk::get_person(fire_person_id));
                                    break;
                                case 2:
                                    pk::play_voice(0x35, pk::get_person(fire_person_id));
                                    break;
                            }
                        }

                        pk::create_fire(unit.pos, pk::rand(1) + 1 + fire_timer, unit, true);

                        if (pk::is_in_screen(building.pos))
                        {
                            switch (pk::rand(4))
                            {
                                case 0:
                                    pk::say(pk::encode("哇哇.."), pk::get_person(무장_병사), unit);
                                    break;
                                case 1:
                                    pk::say(pk::encode("我的脸"), pk::get_person(무장_병사), unit);
                                    break;
                                case 2:
                                    pk::say(pk::encode("火烧过来了, 快躲开! "), pk::get_person(무장_병사), unit);
                                    break;
                                case 3:
                                    pk::say(pk::encode("火.着火了!"), pk::get_person(무장_병사), unit);
                                    break;
                            }
                        }
                    }
                }
            }
        }


    //-------------------------------------------------------------------------------------------------

        void 据点_奏乐效果(pk::building @building)
        {
            int person_id = building.who_has_skill(特技_奏乐);
            if (pk::is_valid_person_id(person_id) and (pk::get_day() == 1))
            {
                if (pk::get_energy(building) < pk::get_max_energy(building) and pk::enemies_around(building))
                {
                    if (pk::is_in_screen(building.pos))
                    {
                        pk::person @person = pk::get_person(person_id);
                        pk::say(pk::encode("恢复士兵们的士气吧"), person);
                        pk::play_se(0x39, building.pos);
                        pk::play_voice(0x37, person);
                    }

                    int cheer_point = pk::core::skill_constant_value(特技_奏乐);
                    if (pk::is_valid_person_id(building.who_has_skill(特技_诗想)))
                        cheer_point *= pk::max(1, pk::core::skill_constant_value(特技_诗想));

                    pk::add_energy(building, cheer_point, true);
                }
            }
        }


    //-------------------------------------------------------------------------------------------------

        void 据点_名声效果(pk::building @building)
        {

            int famous_point = 0;
            int person_id = building.who_has_skill(特技_名声);
            if (pk::is_valid_person_id(person_id) and pk::is_first_month_of_quarter(pk::get_month()) and (pk::get_day() == 1))
            {
                if (pk::get_troops(building) < pk::get_max_troops(building) and pk::enemies_around(building))
                {
                    if (pk::is_in_screen(building.pos))
                    {
                        pk::say(pk::encode("大人!请接受我们成为士兵吧"), pk::get_person(武将_若者), building);
                        pk::play_se(0x39, building.pos);
                        pk::play_voice(0x31, pk::get_person(person_id));
                    }

                    famous_point += (pk::get_person(person_id).stat[武将能力_魅力]) * 10;
                    ch::add_troops(building, famous_point, true);
                }
            }
        }


    //-------------------------------------------------------------------------------------------------

        void 据点_筑城效果(pk::building @building)
        {
            int build_point = 0;
            int person_id = building.who_has_skill(特技_筑城);
            if (pk::is_valid_person_id(person_id))
            {
                if (int(building.hp) < int(pk::get_max_hp(building)))
                {
                    if (pk::is_in_screen(building.pos))
                    {
                        pk::say(pk::encode("跟着我修补城墙!"), pk::get_person(person_id));
                        pk::play_se(0x39, building.pos);

                        switch (pk::rand(2))
                        {
                            case 0:
                                pk::play_voice(0x39, pk::get_person(person_id));
                                break;
                            case 1:
                                pk::play_voice(0x3a, pk::get_person(person_id));
                                break;
                        }
                    }
                    pk::add_hp(building, 50, true);
                }
            }
        }


    //-------------------------------------------------------------------------------------------------

        void 据点_包围效果(pk::building @building)
        {
            int friendly_troops = 0;
            int enemy_punch_units = 0;
            int enemy_units2 = 0;
            int enemy_troops2 = 0;

            auto range = pk::range(building.get_pos(), 1, 2 + (building.facility == 设施_都市 ? 1 : 0));
            for (int i = 0; i < int(range.length); i++)
            {
                auto unit = pk::get_unit(range[i]);
                if (pk::is_alive(unit))
                {
                    int distance = pk::get_distance(building.get_pos(), range[i]);
                    if (pk::is_enemy(building, unit) and distance <= 2)
                    {
                        enemy_units2++;
                        enemy_troops2 += unit.troops;
                        if (unit.weapon == 兵器_投石 or unit.weapon == 兵器_井阑 or unit.weapon == 兵器_冲车 or unit.weapon == 兵器_木兽)
                            enemy_punch_units++;
                    }

                    if (!pk::is_enemy(building, unit) and distance <= 2)
                    {
                        friendly_troops += unit.troops;
                    }
                }
            }
            int 包围倍率 = int(ceil((enemy_troops2 / 10000 + enemy_units2 * 0.3 + enemy_punch_units * 0.5 - friendly_troops / 10000)));

            pk::person @taishu = pk::get_person(pk::get_taishu_id(building));
            int n = 0;
            if (pk::get_taishu_id(building) == -1)
                n = 0;
            else
                n = int(taishu.stat[武将能力_统率] * 0.3 + taishu.stat[武将能力_武力] * 0.1 + taishu.stat[武将能力_智力] * 0.2 + taishu.stat[武将能力_政治] * 0.2 + taishu.stat[武将能力_魅力] * 0.2);
            n = pk::min(n, 100);
            int y = 100 - n / 100 * 50;

            int 士气减少 = pk::max(pk::min(包围倍率 * y / 100, 6), 0);

            // pk::trace(pk::format("城市id：{},城市名:{}包围倍率:{},enemy_units2:{},士气减少:{}", building.get_id(),pk::decode(pk::get_name(building)),包围倍率,enemy_units2,士气减少));

            if (pk::enemies_around(building))
            {
                pk::add_energy(building, -士气减少, true);
            }

        }
        //-------------------------------------------------------------------------------------------------

        void 据点_燃烧效果(pk::building @building)
        {
            bool on_fire = false;
            if (building.facility == 设施_都市)
            {
                array<pk::point> range = pk::range(building.get_pos(), 0, 1);

                for (int i = 0; i < int(range.length); i++)
                {
                    if (pk::is_on_fire(range[i]))
                    {
                        on_fire = true;
                        break;
                    }
                }
            }
            else
            {
                on_fire = (pk::is_on_fire(building.get_pos()));
            }

            if (on_fire)
            {
                pk::add_energy(building, -5, true);

                if (pk::is_in_screen(building.pos) and pk::is_valid_person_id(pk::get_taishu_id(building)))
                {
                    pk::say(pk::encode("城市着火了!快把火扑灭!"), pk::get_person(pk::get_taishu_id(building)), building);
                }
            }
        }


    //-------------------------------------------------------------------------------------------------

    }

    Main main;
}